<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="coinfaces">

        <title>Python对象方法</title>

    <link rel="stylesheet" href="../../theme/css/style.css">
    <link rel="stylesheet" href="../../theme/css/pygments.css">



</head>

<body>
    <div class="content">
<h1>Python对象方法</h1>    <p>
        under
            <a href="../../tags/python/">python</a>
    </p>
    <p>
        in <a href="../../categories/tech/">tech</a>
    </p>
    <p>Published: 2016-10-19</p>


    <p>对象方法可以看成将一个对象和一个函数包装后形成的可调用的新对象。调用对象所产生的效果就是将被绑定的对象添加到参数列表最前面，然后用该新的参数列表调用被绑定的函数。例如如果<tt class="docutils literal">m</tt>是对象<tt class="docutils literal">o</tt>和函数<tt class="docutils literal">f</tt>绑定的结果，则<tt class="docutils literal">m(x, y) = f(o, x, y)</tt>。</p>
<p>Python规定，对象的某属性如果要成为方法，需要满足两个条件：</p>
<ul class="simple">
<li>该属性必须是类属性</li>
<li>该类属性必须是函数类型</li>
</ul>
<p>先解释对象属性和类属性的关系，如果有一个简单的类，并用它生成一个对象：</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">class_data</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">x</span><span class="p">)</span>

<span class="n">a</span> <span class="o">=</span> <span class="n">A</span><span class="p">()</span>
</pre></div>
<p>则<tt class="docutils literal">x</tt>是对象<tt class="docutils literal">a</tt>的属性，但<tt class="docutils literal">show</tt>和<tt class="docutils literal">class_data</tt>不是，但仍可以用<tt class="docutils literal">a.show</tt>或<tt class="docutils literal">a.class_data</tt>来访问它，因为在对象的属性列表里找不到某属性的时候，Python会按一定的顺序搜索其类和基类的同名属性，返回找到的第一个结果或最终甩出<tt class="docutils literal">AttributeError</tt>异常。这里<tt class="docutils literal">a.x</tt>就是对象属性，而<tt class="docutils literal">A.show</tt>和<tt class="docutils literal">A.class_data</tt>就是类属性。</p>
<p><tt class="docutils literal">a.show</tt>是类属性还是对象属性，虽然它最终指向了<tt class="docutils literal">A.show</tt>，但使用起来不一样。调用<tt class="docutils literal">a.show</tt>不需要提供任何参数，因为它绑定了<tt class="docutils literal">a</tt>作为<tt class="docutils literal">show</tt>的第一个参数，即使用别的名称访问它也一样：</p>
<pre class="literal-block">
&gt;&gt;&gt; a.show()
1
&gt;&gt;&gt; f = a.show()
&gt;&gt;&gt; f()
1
</pre>
<p>调用<tt class="docutils literal">A.show</tt>的时候必须提供第一个对象参数：</p>
<pre class="literal-block">
&gt;&gt;&gt; A.show()
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
TypeError: show() missing 1 required positional argument: 'self'
&gt;&gt;&gt; A.show(a)
1
</pre>
<p>因此这里必须作一个概念上的区分，按照Python 3的术语，类属性<tt class="docutils literal">A.show</tt>是函数，而对象属性<tt class="docutils literal">a.show</tt>则是方法，Python 2概念更复杂，但最终表现一样，因此不妨按照Python 3的概念来理解它。如果类属性不是函数，则通过对象访问它还是通过类访问它没有区别。</p>
<p>可以为已定义的类添加方法：</p>
<pre class="literal-block">
&gt;&gt;&gt; A.double = lambda self: self.x * 2
&gt;&gt;&gt; a.double()
2
</pre>
<p>但必须添加为类属性，直接添加到对象属性不会成为方法：</p>
<pre class="literal-block">
&gt;&gt;&gt; a.triple = lambda self: self.x * 3
&gt;&gt;&gt; a.triple()
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
TypeError: &lt;lambda&gt;() missing 1 required positional argument: 'self'
&gt;&gt;&gt; a.triple(a)
3
</pre>
<p>（完）</p>

    </div>
<nav class="nav sidebar">
    <div class="siteinfo">
        <div class="sitename"><a href="../..">coinfaces</a></div>
        <div class="tagline">Another Side of Life</div>
    </div>

        <a href="../../categories/">categories</a>
        <a href="../..">&larr; Home</a>
</nav><footer class="footer">
    <span>
        &copy; jpli &middot;
        under <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA 4.0</a>
    </span>
    |
    <span>
        Powered by:
        <a href="http://blog.getpelican.com/">Pelican</a>
    </span>
</footer></body>
</html>